package com.gitee.openviducn.inspector.manager;

import com.gitee.openviducn.inspector.common.BizException;
import com.gitee.openviducn.inspector.common.ResponseError;
import com.gitee.openviducn.inspector.domain.vo.response.openvidu.RecordingVO;
import io.openvidu.java.client.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author: https://gitee.com/wesleyOne
 * @Date: 04.19 2020
 */
@Slf4j
@Component
public class RecordManager {

    @Resource
    private OpenViduManager openViduManager;

    /**
     * 开始录制
     * 200: 会话录制开始。收到响应的同时，视频文件已经创建并包含适当的数据，并且可以保证停止录制
     * 400: 请求参数异常
     * 422: resolution 参数超过可接受的值（宽和高范围100px-1999px）或者是 hasAudio 和 hasVideo 属性都是 false
     * 404: 传递的 sessionId 参数不存在
     * 406: 会话没有连接的参与者
     * 409: 会话的 MediaMode 没有设置成 ROUTED ，或者以及在录制了
     * 501: OpenVidu Server 的录制模块未启用 (OPENVIDU_RECORDING 属性被设置成 false)
     */
    public RecordingVO startRecording(String hostname, String sessionId) throws OpenViduJavaClientException, BizException {
        RecordingProperties properties = new RecordingProperties.Builder().build();
        OpenVidu openVidu = openViduManager.getOpenVidu(hostname);
        if (Objects.isNull(openVidu)) {
            return null;
        }
        try {
            Recording recording = openVidu.startRecording(sessionId, properties);
            openViduManager.forceRefreshOpenViduCache(hostname);
            return RecordingVO.build(recording);
        } catch (OpenViduHttpException e) {
            int status = e.getStatus();
            String errMsg;
            switch (status) {
                case 400:
                    errMsg = "请求参数异常";
                    break;
                case 422:
                    errMsg = "resolution 参数超过可接受的值（宽和高范围100px-1999px）或者是 hasAudio 和 hasVideo 属性都是 false";
                    break;
                case 404:
                    errMsg = "传递的 sessionId 参数不存在";
                    break;
                case 406:
                    errMsg = "会话没有连接的参与者";
                    break;
                case 409:
                    errMsg = "会话的 MediaMode 没有设置成 ROUTED ，或者已经在录制了";
                    break;
                case 501:
                    errMsg = "OpenVidu Server 的录制模块未启用 (OPENVIDU_RECORDING 属性被设置成 false)";
                    break;
                default:
                    errMsg = "未知异常";
            }
            throw new BizException(ResponseError.OPENVIDU_HTTP_ERR, errMsg);
        }
    }

    /**
     * 停止录制
     * 200: 会话成功停止录制。视频文件已准备好进行复制reproduction
     * 404: 参数RECORDING_ID不存在
     * 406: 录制处于 starting 状态。只有到 started 状态才能停止录制
     */
    public RecordingVO stopRecording(String hostname, String recordingId) throws OpenViduJavaClientException, BizException {
        OpenVidu openVidu = openViduManager.getOpenVidu(hostname);
        if (Objects.isNull(openVidu)) {
            return null;
        }
        try {
            Recording recording = openVidu.stopRecording(recordingId);
            openViduManager.forceRefreshOpenViduCache(hostname);
            return RecordingVO.build(recording);
        } catch (OpenViduHttpException e) {
            int status = e.getStatus();
            String errMsg;
            switch (status) {
                case 404:
                    errMsg = "参数RECORDING_ID不存在";
                    break;
                case 406:
                    errMsg = "录制处于 starting 状态。只有到 started 状态才能停止录制";
                    break;
                default:
                    errMsg = "未知异常";
            }
            throw new BizException(ResponseError.OPENVIDU_HTTP_ERR, errMsg);
        }

    }

    /**
     * 获取录制信息
     */
    public RecordingVO getRecording(String hostname, String recordingId) throws OpenViduJavaClientException, BizException {
        OpenVidu openVidu = openViduManager.getOpenVidu(hostname);
        if (Objects.isNull(openVidu)) {
            return null;
        }
        try {
            Recording recording = openVidu.getRecording(recordingId);
            return RecordingVO.build(recording);
        } catch (OpenViduHttpException e) {
            int status = e.getStatus();
            String errMsg;
            if (status == 404) {
                errMsg = "参数RECORDING_ID不存在";
            } else {
                errMsg = "未知异常";
            }
            throw new BizException(ResponseError.OPENVIDU_HTTP_ERR, errMsg);
        }
    }

    /**
     * 获取录制信息
     */
    public List<RecordingVO> listRecordings(String hostname) throws OpenViduJavaClientException, OpenViduHttpException {
        OpenVidu openVidu = openViduManager.getOpenVidu(hostname);
        if (Objects.isNull(openVidu)) {
            return null;
        }
        List<Recording> recordings = openVidu.listRecordings();
        return recordings.stream().map(RecordingVO::build).collect(Collectors.toList());
    }

    /**
     * 删除录制文件
     */
    public void deleteRecording(String hostname, String recordingId) throws OpenViduJavaClientException, OpenViduHttpException {
        OpenVidu openVidu = openViduManager.getOpenVidu(hostname);
        if (Objects.isNull(openVidu)) {
            return;
        }
        openVidu.deleteRecording(recordingId);
        openViduManager.forceRefreshOpenViduCache(hostname);
    }
}
